// Edit a filetype action
void filetypeed_edit_action(
	filetype_ed_data *data,
	short action,
	char *name)
{
	Cfg_Function *function;
	FunctionStartup *startup;
	BOOL success=0;

	// Allocate startup data
	if (!(startup=AllocVec(sizeof(FunctionStartup),MEMF_CLEAR)))
		return;

	// Find the function we want to edit
	if (!(function=FindFunctionType(&data->type->function_list,action)))
	{
		// Allocate a new function
		function=NewFunction(0,action);
	}

	// Otherwise, copy the function
	else function=CopyFunction(function,0,0);

	// Valid function?
	if (function)
	{
		// Copy startup data
		*startup=data->func_startup;
		startup->window=data->window;
		startup->function=function;
		startup->owner_ipc=data->ipc;
		startup->object=data->type;
		startup->object_flags=action;

		// Build title
		lsprintf(startup->title,"%s : %s",data->type->type.name,name);

		// Launch editor
		if ((IPC_Launch(
			&data->proc_list,
			&data->editor[action],
			"dopus_function_editor",
			(ULONG)IPC_NATIVE(FunctionEditor),
			STACK_DEFAULT,
			(ULONG)startup,
			(struct Library *)DOSBase)) && data->editor[action]) success=1;
	}

	// Free data if not successful
	if (!success)
	{
		FreeFunction(function);
		FreeVec(startup);
	}
}
void FunctionEditor(void)
{
	struct IntuiMessage *gmsg,msg;
	int break_flag=0;
	UWORD gadgetid=0;
	ULONG waitbits;
	FuncEdData *data;
	IPCData *ipc;
	NewConfigWindow newwin;
	FunctionStartup *startup=0;
	IPCMessage *submsg;
	int success=0;
	BOOL open_window=1;
	BPTR lock;
	ConfigWindow windims;

	// Do startup
	if (!(ipc=Local_IPC_ProcStartup((ULONG *)&startup, (APTR)&funced_init)))
	{
		funced_cleanup(startup->data);
		return;
	}

	// Get data pointer
	data=startup->data;

	// Lock RAM: and CD to it
	if ((lock=Lock("ram:",ACCESS_READ)))
		lock=CurrentDir(lock);

	// Copy dimensions
	if (startup->flags&FUNCEDF_CENTER)
		windims=_function_editor_window_center;
	else
	if (startup->flags&FUNCEDF_LABEL)
		windims=_function_editor_label_window;
	else
		windims=_function_editor_window;

	// Fill in new window
	newwin.parent=startup->window;
	newwin.dims=&windims;
	newwin.title=(startup->title[0])?startup->title:(char *)GetString(startup->locale,MSG_FUNCED_TITLE);
	newwin.locale=startup->locale;
	newwin.port=0;
	newwin.flags=WINDOW_VISITOR|WINDOW_AUTO_KEYS|WINDOW_REQ_FILL;//|WINDOW_SIZE_BOTTOM;
	newwin.font=0;

	// Build flag list
	funced_build_flaglist(data);
	waitbits=1<<ipc->command_port->mp_SigBit|1<<data->drag.timer->port->mp_SigBit;

	// Event loop
	FOREVER
	{
		// Check drag
		if (config_drag_check(&data->drag))
		{
			// End drag
			functioned_end_drag(data,0);
		}

		// Task message?
		while ((submsg=(IPCMessage *)GetMsg(ipc->command_port)))
		{
			// Close message?
			if (submsg->command==IPC_QUIT)
			{
				// Keep changes?
				success=submsg->flags;

				// Set break flag
				break_flag=1;
			}

			// Activate
			else
			if (submsg->command==IPC_ACTIVATE && data->window)
			{
				WindowToFront(data->window);
				ActivateWindow(data->window);
			}

			// Hide
			else
			if (submsg->command==IPC_HIDE && data->window)
			{
				// Store changes in function
				funced_store_edits(data);

				// End any drag in progress
				functioned_end_drag(data,0);

				// Remove AppWindow
				RemoveAppWindow(data->appwindow);
				data->appwindow=0;

				// Close window
				CloseConfigWindow(data->window);

				// Zero stuff
				data->window=0;
				data->objlist=0;
				waitbits=1<<ipc->command_port->mp_SigBit;
			}

			// Show
			else
			if (submsg->command==IPC_SHOW && !data->window)
			{
				// Set flag to open window
				open_window=1;
				newwin.parent=(struct Window *)submsg->data;
			}

			// Passed-along app message
			else
			if (submsg->command==CFG_APPMESSAGE_PASS)
			{
				funced_appmsg(data,submsg->data);
				ReplyMsg((struct Message *)submsg->data);
			}

			// Update our identity
			else
			if (submsg->command==CFG_NEW_ID)
			{
				data->function->function.func_type=submsg->flags;
				startup->object_flags=(ULONG)submsg->data;
			}

			// Copy a function
			else
			if (submsg->command==FUNCTIONEDIT_COPY_LINE)
			{
				FunctionEntry *entry,*next;

				// Copy function
				functioned_copy_line(
					data,
					(FunctionEntry *)submsg->data,
					0,
					(Point *)submsg->data_free);

				// Free function
				entry=(FunctionEntry *)submsg->data;
				while (entry)
				{
					// Get next
					next=(FunctionEntry *)entry->node;

					// Free entry
					FreeVec(entry);
					entry=next;
				}
			}

			// Clip button
			else
			if (submsg->command==BUTTONEDIT_CLIP_BUTTON)
			{
				Cfg_ButtonFunction *func;

				// Show busy pointer
				SetWindowBusy(data->window);

				// Stop editing
				funced_end_edit(data,data->edit_node,0,0);
				data->edit_node=0;

				// Get first function
				if ((func=(Cfg_ButtonFunction *)
					FindFunctionType(
						(struct List *)&((Cfg_Button *)submsg->data)->function_list,
						FTYPE_LEFT_BUTTON)))
				{
					FunctionEntry dummy;
					Cfg_Instruction *ins;

					// Go through instructions
					for (ins=(Cfg_Instruction *)func->instructions.mlh_Head;
						ins->node.mln_Succ;
						ins=(Cfg_Instruction *)ins->node.mln_Succ)
					{
						// Fill out dummy entry
						dummy.type=ins->type;
						if (ins->string) strcpy(dummy.buffer,ins->string);
						else dummy.buffer[0]=0;

						// Copy function line
						data->edit_node=funced_new_entry(data,0,&dummy);
					}

					// Start editing last line
					funced_start_edit(data);

					// Get flags
					data->function->function.flags=func->function.flags;
					data->function->function.code=func->function.code;
					data->function->function.qual=func->function.qual;
					data->function->function.qual_mask=func->function.qual_mask;
					data->function->function.qual_same=func->function.qual_same;

					// Update flag list
					funced_update_flaglist(data);

					// Update key
					funced_show_key(data);
				}

				// Free button
				FreeButton((Cfg_Button *)submsg->data);

				// Clear busy pointer
				ClearWindowBusy(data->window);
			}

			// Reply the message
			IPC_Reply(submsg);
		}

		// Open window?
		if (open_window)
		{
			// Open window
			if (!(data->window=OpenConfigWindow(&newwin)) ||
				!(data->p_objlist=AddObjectList(
					data->window,
					(startup->flags&FUNCEDF_IMAGE)?_function_editor_image_objects:
						((startup->flags&FUNCEDF_LABEL)?_function_editor_label_objects:
														_function_editor_normal_objects))) ||
				!(data->objlist=AddObjectList(data->window,_function_editor_objects)))
				break;

			// Add use or save button
			AddObjectList(data->window,(startup->flags&FUNCEDF_SAVE)?_function_editor_objects_save:_function_editor_objects_use);

			// Store window for drag
			data->drag.window=data->window;

			// Set window ID
			SetWindowID(data->window,0,WINDOW_FUNCTION_EDITOR,(struct MsgPort *)ipc);

			// Add menus
			AddWindowMenus(data->window,_funced_menus);

			// Make this an AppWindow
			data->appwindow=AddAppWindowA(0,0,data->window,data->appport,0);

			// Get waitbits
			waitbits|=1<<data->window->UserPort->mp_SigBit;
			if (data->appwindow) waitbits|=1<<data->appport->mp_SigBit;

			// Disable key?
			if (startup->flags&FUNCEDF_NO_KEY)
			{
				DisableObject(data->objlist,GAD_FUNCED_KEY,TRUE);
			}

			// Initialise gadgets with function data.
			funced_init_gads(data);
			open_window=0;
		}

		// Intuimessage
		if (data->window)
		{
			while ((gmsg=GetWindowMsg(data->window->UserPort)))
			{
				Att_Node *node;

				// Copy message and reply (unless IDCMPUPDATE)
				msg=*gmsg;
				if (gmsg->Class!=IDCMP_IDCMPUPDATE)
				{
					ReplyWindowMsg(gmsg);
					gmsg=0;
				}

				// Get GadgetID
				if (msg.Class==IDCMP_GADGETDOWN ||
					msg.Class==IDCMP_GADGETUP)
					gadgetid=((struct Gadget *)msg.IAddress)->GadgetID;

				// Look at message
				switch (msg.Class)
				{
					// Key press
					case IDCMP_VANILLAKEY:

						// If editing something, activate string gadget
						if (data->edit_node)
							ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_EDIT)),data->window);
						break;


					// Close window
					case IDCMP_CLOSEWINDOW:

						// Set break flag
						break_flag=1;
						break;


					// Mouse move
					case IDCMP_MOUSEMOVE:

						// Handle drag move
						config_drag_move(&data->drag);
						break;


					// Inactive window does menu down
					case IDCMP_INACTIVEWINDOW:
						msg.Code=MENUDOWN;

					// Mouse buttons
					case IDCMP_MOUSEBUTTONS:

						// Valid drag info?
						if (data->drag.drag)
						{
							short ok=-1;

							// Dropped ok?
							if (msg.Code==SELECTUP)
							{
								// Is shift down?
								if (msg.Qualifier&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
									data->drag_shift=1;
								else data->drag_shift=0;

								// Remember last position
								data->drag.drag_x=data->window->WScreen->MouseX;
								data->drag.drag_y=data->window->WScreen->MouseY;
								ok=1;
							}

							// Aborted
							else
							if (msg.Code==MENUDOWN)
							{
								// Set abort
								ok=0;
							}

							// End drag?
							if (ok!=-1) functioned_end_drag(data,ok);
						}
						break;


					// Menu
					case IDCMP_MENUPICK:

						{
							struct MenuItem *item;

							// Get item
							if (!(item=ItemAddress(data->window->MenuStrip,msg.Code)))
								break;

							// Treat as gadget
							gadgetid=MENUID(item);
						}

					// Gadget
					case IDCMP_GADGETUP:
					case IDCMP_GADGETDOWN:

						// Look at gadget ID
						switch (gadgetid)
						{
							// Hotkey
							case GAD_FUNCED_KEY:
								{
									IX ix;
									char *ptr;

									// Get key, see if it's invalid
									if ((ptr=(char *)GetGadgetValue(data->objlist,GAD_FUNCED_KEY)) && *ptr)
									{
										// Try to parse
										if (ParseIX(ptr,&ix))
										{
											// Flash screen
											DisplayBeep(data->window->WScreen);

											// Activate key field again
											ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_KEY)),data->window);
										}
										else
										{
											data->function->function.code=ix.ix_Code;
											data->function->function.qual=QualValid(ix.ix_Qualifier);
											data->function->function.qual_mask=ix.ix_QualMask;
											data->function->function.qual_same=ix.ix_QualSame;
										}
									}
								}
								break;


							// Flag selected
							case GAD_FUNCED_FLAGS:

								// Get selected node
								node=Att_FindNode(data->flag_list,msg.Code);

								// Set flag
								data->function->function.flags^=node->data;

								// Check change
								funced_check_flag(&data->function->function.flags,node->data);

								// Update flag list
								funced_update_flaglist(data);
								break;


							// Edit a line
							case GAD_FUNCED_LISTER:

								// Get selected node
								node=Att_FindNode(data->func_display_list,msg.Code);

								// Is this the node we're already editing?
								if (node==data->edit_node) break;

								// If we're editing another one, store its contents
								if (data->edit_node)
									funced_end_edit(data,data->edit_node,0,0);

								// Start editing this entry
								data->edit_node=node;
								funced_start_edit(data);
								break;


							// Return pressed in edit line
							case GAD_FUNCED_EDIT:

								// See if we were editing something
								if (data->edit_node)
								{
									// Stop editing
									funced_end_edit(data,data->edit_node,END_DISABLE,msg.Qualifier);
									data->edit_node=0;
								}
								break;


							// New entry
							case GAD_FUNCED_NEW_ENTRY:
							case GAD_FUNCED_INSERT_ENTRY:

								// Create new entry
								functioned_copy_line(data,0,gadgetid,0);
								break;


							// Delete entry
							case GAD_FUNCED_DELETE_ENTRY:
								// Check we were editing something
								if (!data->edit_node) break;

								// Stop editing (signal delete)
								funced_end_edit(data,data->edit_node,END_DISABLE|END_DELETE,0);
								data->edit_node=0;
								break;


							// Function type
							case GAD_FUNCED_FUNCTION_TYPE:
								// Check we were editing something
								if (!data->edit_node) break;

								// Store type
								((FunctionEntry *)data->edit_node->data)->type=msg.Code;

								// Disable popup button if no functions
								DisableObject(
									data->objlist,
									GAD_FUNCED_EDIT_GLASS,
									(msg.Code==INST_COMMAND && !data->startup->func_list));
								break;


							// Glass gadget
							case GAD_FUNCED_EDIT_GLASS:

								// Check we were editing something
								if (data->edit_node)
								{
									char buffer[256];

									// Put up requester
									if (!(funced_command_req(
										data,
										buffer,
										((FunctionEntry *)data->edit_node->data)->type)))
										break;

									// Insert string in edit line
									funced_edit_insertstring(
										data->objlist,
										GAD_FUNCED_EDIT,
										buffer,
										DOpusBase,(struct Library *)IntuitionBase);
								}
								break;


							// Argument list
							case GAD_FUNCED_EDIT_ARGUMENT:

								// Check we were editing something
								if (data->edit_node)
								{
									char buffer[80];

									// Put up requester
									if (!(funced_command_req(
										data,
										buffer,
										-1))) break;

									// Insert string in edit line
									funced_edit_insertstring(
										data->objlist,
										GAD_FUNCED_EDIT,
										buffer,
										DOpusBase,(struct Library *)IntuitionBase);
								}
								break;


							// Export
							case MENU_FUNCED_EXPORT_ASCII:
							case MENU_FUNCED_EXPORT_CMD:

								// Got file requester?
								if (WINREQUESTER(data->window))
								{
									struct TagItem tags[6];
									struct FileRequester *req=WINREQUESTER(data->window);

									// Show busy pointer
									SetWindowBusy(data->window);

									// File requester tags
									tags[0].ti_Tag=ASLFR_Window;
									tags[0].ti_Data=(ULONG)data->window;
									tags[1].ti_Tag=ASLFR_TitleText;
									tags[1].ti_Data=(ULONG)GetString(startup->locale,MSG_FUNCED_SELECT_FILE);
									tags[2].ti_Tag=ASLFR_Flags1;
									tags[2].ti_Data=FRF_DOSAVEMODE|FRF_PRIVATEIDCMP;
									tags[3].ti_Tag=ASLFR_Flags2;
									tags[3].ti_Data=FRF_REJECTICONS;
									tags[4].ti_Tag=(gadgetid==MENU_FUNCED_EXPORT_CMD)?ASLFR_InitialDrawer:TAG_DONE;
									tags[4].ti_Data=(ULONG)"DOpus5:Commands";
									tags[5].ti_Tag=TAG_DONE;

									// Show filerequester
									if (AslRequest(req,tags))
									{
										// Build filename
										strcpy(data->buffer,req->fr_Drawer);
										AddPart(data->buffer,req->fr_File,256);

										// Store changes in function
										funced_store_edits(data);

										// Do export
										if (gadgetid==MENU_FUNCED_EXPORT_CMD)
											function_export_cmd(data->buffer,0,data->function);
										else
											L_FunctionExportASCII(data->buffer,0,data->function,startup->a4);
									}

									// Remove busy pointer
									ClearWindowBusy(data->window);
								}
								break;


							// Cut/Copy
							case MENU_FUNCED_CUT:
							case MENU_FUNCED_COPY:
								{
									APTR iff;

									// Set busy pointer
									SetWindowBusy(data->window);

									// Open clipboard
									if ((iff=IFFOpen((char *)0,IFF_CLIP_WRITE,ID_OPUS)))
									{
										// Stop editing
										funced_end_edit(data,data->edit_node,END_DISABLE,0);
										data->edit_node=0;

										// Store changes in function
										funced_store_edits(data);

										// Save function
										SaveFunction(iff,data->function);

										// Close clipboard
										IFFClose(iff);
									}

									// Just copy, not cut?
									if (gadgetid==MENU_FUNCED_COPY)
									{
										// Clear busy pointer
										ClearWindowBusy(data->window);
										break;
									}

									// Fall through, paste null function
								}

							// Paste
							case MENU_FUNCED_PASTE:
								{
									Cfg_Function *func=0;

									// Set busy pointer
									SetWindowBusy(data->window);

									// End any edit
									funced_end_edit(data,data->edit_node,END_DISABLE,0);
									data->edit_node=0;

									// Paste?
									if (gadgetid==MENU_FUNCED_PASTE)
									{
										APTR iff;

										// Open clipboard
										if ((iff=IFFOpen((char *)0,IFF_CLIP_READ,ID_OPUS)))
										{
											// Find function
											if (IFFNextChunk(iff,ID_FUNC))
											{
												// Read function
												func=ReadFunction(iff,0,0,0);
											}

											// Close clipboard
											IFFClose(iff);
										}

										// No valid function?
										if (!func)
										{
											// Flash error
											DisplayBeep(data->window->WScreen);
											ClearWindowBusy(data->window);
											break;
										}
									}

									// Detach existing list
									SetGadgetChoices(data->objlist,GAD_FUNCED_FLAGS,(APTR)~0);

									// Clear function list
									Att_RemList(data->function_list,REMLIST_SAVELIST|REMLIST_FREEDATA);

									// Free existing instructions
									FreeInstructionList(data->function);

									// Rebuild display list
									funced_build_display(data);

									// Clear flags
									data->function->function.flags=0;
									funced_update_flaglist(data);

									// Clear key
									data->function->function.code=0xffff;
									SetGadgetValue(data->objlist,GAD_FUNCED_KEY,0);

									// Clear label
									if (startup->flags&FUNCEDF_LABEL)
									{
										data->label[0]=0;
										SetGadgetValue(data->p_objlist,GAD_FUNCED_LABEL,0);
									}

									// Paste function in?
									if (func)
									{
										short type;

										// Save type
										type=data->function->function.func_type;

										// Copy function in
										CopyFunction(func,0,data->function);
										data->function->function.func_type=type;

										// Free copied function
										FreeFunction(func);

										// Initialise gadgets
										funced_init_gads(data);
									}
	
									// Clear busy pointer
									ClearWindowBusy(data->window);
								}
								break;


							// Use
							case GAD_FUNCED_USE:
								success=1;

							// Cancel
							case GAD_FUNCED_CANCEL:
								break_flag=1;
								break;
						}
						break;


					// Key press
					case IDCMP_RAWKEY:

						// Help?
						if (msg.Code==0x5f &&
							!(msg.Qualifier&VALID_QUALIFIERS))	
						{
							// Set busy pointer
							SetWindowBusy(data->window);

							// Send help command
							IPC_Command(startup->main_owner,IPC_HELP,(1<<31),"Function Editor",0,REPLY_NO_PORT);

							// Clear busy pointer
							ClearWindowBusy(data->window);
						}
						break;


					// BOOPSI message
					case IDCMP_IDCMPUPDATE:
						{
							struct TagItem *tags=(struct TagItem *)msg.IAddress;
							short item;

							// Check ID
							if (GetTagData(GA_ID,0,tags)!=GAD_FUNCED_LISTER)
								break;

							// Get item
							if ((item=GetTagData(DLV_DragNotify,-1,tags))!=-1)
							{
								// Start the drag
								config_drag_start(&data->drag,data->func_display_list,item,tags,TRUE);
							}
						}
						break;


					// Ticks
					case IDCMP_INTUITICKS:
						++data->drag.tick_count;
						break;
				}

				// Reply to any outstanding message
				if (gmsg) ReplyWindowMsg(gmsg);
			}
		}

		// AppMessage
		if (data->appwindow)
		{
			struct AppMessage *msg;

			while ((msg=(struct AppMessage *)GetMsg(data->appport)))
			{
				// Make sure window is active
				ActivateWindow(data->window);

				// Handle message
				funced_appmsg(data,msg);
				ReplyMsg((struct Message *)msg);
			}
		}

		// Check break flag
		if (break_flag) break;

		// Wait for message
		Wait(waitbits);
	}

	// Restore CD
	if (lock) UnLock(CurrentDir(lock));

	// Edit successful?
	if (success)
	{
		FunctionReturn ret;

		// Store changes in function
		funced_store_edits(data);

		// Fill out return data
		ret.object=startup->object;
		ret.object_flags=startup->object_flags;
		ret.function=data->function;

		// Send new function back
		IPC_Command(startup->owner_ipc,FUNCTIONEDIT_RETURN,0,&ret,0,REPLY_NO_PORT);
	}

	// End any drag in progress
	functioned_end_drag(data,0);

	// Free edit function
	FreeFunction(data->function);

	// Close window
	RemoveAppWindow(data->appwindow);
	CloseConfigWindow(data->window);

	// Close application port
	if (data->appport)
	{
		struct Message *msg;
		while ((msg=GetMsg(data->appport)))
			ReplyMsg(msg);
		DeleteMsgPort(data->appport);
	}

	// Say goodbye
	IPC_Goodbye(ipc,startup->owner_ipc,startup->object_flags);

	// Delete IPC data
	Forbid();
	IPC_Free(ipc);

	// Free data
	funced_cleanup(data);
	FreeVec(startup);
}
// Receive edit from function editor
short filetypeed_receive_edit(
	filetype_ed_data *data,
	FunctionReturn *ret)
{
	Cfg_Function *function=0;
	Cfg_Function *func_copy=0;
	BOOL no_func=0,icon=0;
	func_node *fndata=0;
	short success=0;

	// Is the new function empty?
	if (IsListEmpty((struct List *)&ret->function->instructions))
		no_func=1;

	// Try to copy the new function
	if (no_func ||
		(func_copy=CopyFunction(ret->function,0,0)))
	{
		// Icon menu? (this is a bit kludgy)
		if (ret->object_flags>15)
		{
			Att_Node *node;

			// Go through icon list
			for (node=(Att_Node *)data->icon_list->list.lh_Head;
				node->node.ln_Succ;
				node=(Att_Node *)node->node.ln_Succ)
			{
				// Match function
				if (((func_node *)node->data)->func==(Cfg_Function *)ret->object_flags)
				{
					// Get function pointer
					function=(Cfg_Function *)ret->object_flags;
					break;
				}
			}

			icon=1;
		}

		// Otherwise, find the function we want to replace
		else function=FindFunctionType(&data->type->function_list,ret->object_flags);

		// Add new function to the list
		if (func_copy)
		{
			// Fix type
			if (!icon) func_copy->function.func_type=ret->object_flags;

			// Add to list, in same position if applicable
			if (function) Insert(&data->type->function_list,&func_copy->node,&function->node);
			else AddTail(&data->type->function_list,&func_copy->node);
		}

		// Free old function
		if (function)
		{
			// Remove function and free it
			Remove(&function->node);
			FreeFunction(function);
		}

		// Store for icon menu
		if (fndata) fndata->func=func_copy;

		success=(icon)?2:1;
	}

	return success;
}
Exemple #4
0
// Most of the work is done in main()...
int main( int argc, char* argv[] ) {

  // Print out help message if needed.
  if (argc != 2) {
      printf("*** Code Crypt 0.0 by [email protected] ***\n");
      printf("***                                                 ***\n");
      printf("*** Usage: codecrypt filename.exe                   ***\n");
      printf("*** Will encrypt the codesection to avoid detection ***\n");
      printf("*** Disclaimer: This software is for educational    ***\n");
      printf("*** purposes only.  No responsibility is held or    ***\n");
      printf("*** accepted for misuse.                            ***\n");
      return 0;
    }
  
  // The file to pack is the 1st argument.
  LPCSTR fileName = argv[1];

  // Open the .exe file to be packed.
  HANDLE hFile = CreateFileA(
                             fileName,
			     GENERIC_WRITE | GENERIC_READ,
			     FILE_SHARE_READ | FILE_SHARE_WRITE,
			     NULL,
			     OPEN_EXISTING,
			     FILE_ATTRIBUTE_NORMAL,
			     NULL);

  // Did the file open work?
  if (hFile == INVALID_HANDLE_VALUE) {
    DWORD x = GetLastError();
    // No, get out.
    printf("Cannot open file '%s'...exiting!\n", argv[1]);
    char *buf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		  FORMAT_MESSAGE_FROM_SYSTEM |
		  FORMAT_MESSAGE_IGNORE_INSERTS,
		  NULL,x,0,
		  (LPTSTR) &buf,0,NULL);
    printf("Error: %d, Error Code:%d\n", buf, x);
    return 1;
  }

  // Get size of file. This is needed because we need to tell the
  // CreateFileMapping function to add memory to the end of the
  // memory-mapped file. We will later use this memory to add in the
  // unpacker stub and its required data.
  LARGE_INTEGER bigInt;
  BOOL r = GetFileSizeEx(hFile, &bigInt);
  if (!r) {
    printf("Cannot get file size.\n");
    return 1;
  }

  // Is the file too big to add in the unpacker stub?
  DWORD fileSize = bigInt.LowPart;
  if (fileSize + 0x2000 >= ULONG_MAX) {
    printf("The file is too big to pack.\n");
    return 1;
  }

  // Create a handle to a memory mapped file. Note that this does not
  // actually map the file, it just creates the handle that will actually be
  // mapped later. Note that extra space is allocated at the end to
  // the mapped file for the unpacker stub.
  HANDLE hFileMap = CreateFileMapping(hFile, 
				      NULL, 
				      PAGE_READWRITE,
				      bigInt.HighPart,
				      bigInt.LowPart + 0x2000 ,
				      NULL);
    
  // Did creating the file mapping handle work?
  if (hFileMap == NULL) {
    printf("Unable to create file mapping! Exiting...");
    return 1;
  }

  // Map the .exe file into memory. The map is set up so we can read and
  // write to it.
  LPVOID hMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  // Did mapping the file to memory work?
  if (hMap == NULL) {
    printf("Unable to map file into memory! Exiting...");
    return 1;
  }

  // Get the DOS header from the .exe file. This is the 1st thing in the
  // file.
  PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMap;

  // This packer only works with .exe files. Make sure we have one.
  // The e_magic field tells us what sort of file this is.
  if (!(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)) {
    printf("This packer only works with .exe files.\n");
    return 1;
  }

  // Get the IMAGE_NT_HEADER. This has 3 fields, the signature (which should
  // be set 0x00004550 for valid PE files), the file header, and the
  // optional file header.
  PIMAGE_NT_HEADERS pNTHeader;
  // The e_lfanew field in the DOS header gives us the offset to the
  // IMAGE_NT_HEADER.
  pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew);

  // Check to make sure this is a PE file we are working with.
  if (!(pNTHeader->Signature == IMAGE_NT_SIGNATURE)) {
    printf("This packer only works with PE files.\n");
    printf("Signature for PE files is %x. Current signature is %x\n",
           IMAGE_NT_SIGNATURE, pNTHeader->Signature);
    return 1;
  }

  // The entire .exe image is stored in a HMODULE structure. Cast the memory
  // mapped file so it can be viewed as an HMODULE.
  HMODULE *hModule = (HMODULE *) hMap;

  // Grab a pointer to the IMAGE_OPTIONAL_HEADER structure, which contains
  // information about the size of the code and all data sections, where to
  // find the sections, etc.
  //
  // The IMAGE_OPTIONAL_HEADER structure is contained in the IMAGE_NT_HEADER
  // in the OptionalHeader field.
  //
  // Note that we are assuming that we are working with a 32bit executable.
  PIMAGE_OPTIONAL_HEADER32 optionHeader =
    (PIMAGE_OPTIONAL_HEADER32) &(pNTHeader->OptionalHeader);

  // Get the RVA (relative virtual address) of the first byte of code when
  // loaded into memory. To find the actual address of the code add the load
  // address (in this case the address of hModule) to the RVA.
  VOID* baseCodeRVA = (VOID*)optionHeader->BaseOfCode;

  // Get the combined size of all code sections.
  DWORD codeSize = optionHeader->SizeOfCode;

  // TCC does not seem to set the SizeOfCode field, so executables
  // compiled with TCC cannot be packed with this packer.
  if (codeSize < 1) {
    printf("SizeOfCode field is < 1. Cannot pack.\n");
    printf("The execuatble may have been compiled with TCC.\n");
    return 1;
  }

  // After the MAGE_NT_HEADERS is the section table. The section table is an
  // array of IMAGE_SECTION_HEADERs structures. An IMAGE_SECTION_HEADER
  // provides information about its associated section.
  //
  // Use the IMAGE_FIRST_SECTION macro defined in winnt.h to get the address
  // of the 1st IMAGE_SECTION_HEADER.

  // DQ (4/23/2017): I don't see that this macro will work with WINE (modified to support testing).
  // IMAGE_SECTION_HEADER* firstSectionHeader = 
  //  IMAGE_FIRST_SECTION32(pNTHeader);
  IMAGE_SECTION_HEADER* firstSectionHeader = NULL;

  // Get a pointer to the code block. The code block is found by adding the
  // base load address to the code RVA.
  PVOID codePtr = MakePtr(void *, hModule, baseCodeRVA);

  // Unprotect the code so we can encrypt it in place.
  DWORD oldProt = 0;
  BOOL diditwork = 
    VirtualProtect(codePtr, codeSize, PAGE_READWRITE, &oldProt);
    
  // Did the code unprotection work?
  if (!diditwork) {
    DWORD x = GetLastError();
    printf("Cannot unprotect code (error code %d).\n", x);
    return 0;
  }

  // Find the section containing the code. We have already
  // calculated the code relative virtual base address
  // (baseCodeRVA), so now we need to find the section whose base
  // RVA is the same as the RVA of the code.
  IMAGE_SECTION_HEADER* codeSection = 
    FindSection(firstSectionHeader, 
		pNTHeader->FileHeader.NumberOfSections, 
		(DWORD) baseCodeRVA);

  // Can we find the section with the code?
  if (codeSection == NULL) {
    printf("Cannot find code section.\n");
    return 0;
  }

  // Get the raw memory address (inside HMODULE) and size of the code.
  DWORD rawCodePosition = codeSection->PointerToRawData;
  DWORD virtualCodeSize = codeSection->Misc.VirtualSize;

  // Compute the actual, in-memory start and end address of the code
  // block.
  DWORD startpos = (DWORD)hModule + (DWORD)rawCodePosition;
  DWORD endpos = startpos + virtualCodeSize;
 
  // Encrypt the code by incrementing each byte in the code by 1.
  printf("Starting to encrypt code section...\n");
  DWORD currAddr;
  for (currAddr = startpos; currAddr < endpos; currAddr++) {
    (*((char *) currAddr))++;
  }
  printf("Done encrypting code section.\n");

  // Get the last section. We will be tacking the unpacking code
  // onto the end of the last section (if we have room).
  IMAGE_SECTION_HEADER* lastSection = 
    FindLastSection(firstSectionHeader, 
		    pNTHeader->FileHeader.NumberOfSections);

  char sectName[10];
  int i;
  for (i = 0; i < 8; i++) {
    sectName[i] = lastSection->Name[i];
  }
  sectName[8] = '\0';
  printf("Adding stub to section: name = %s, Raw size = %d, Raw Data ptr = %d\n", 
         sectName, 
	 lastSection->SizeOfRawData, 
	 lastSection->PointerToRawData);
    
  // We will be adding the unpacker stub to the last section in the
  // PE file. In that section, we will be adding the unpacker stub
  // code right after the existing data in the section.
  DWORD* storageSpot = (DWORD*)((DWORD)hModule + 
				(DWORD)lastSection->PointerToRawData +
				(DWORD)lastSection->SizeOfRawData);

  // Get the unpacking code and store it in a contiguous chunk of memory.
  char *decryptRoutine = CopyFunction(&DecryptAndStart);
  DWORD decryptSize = GetFunctionSize(&DecryptAndStart);
  if (decryptSize > 0x2000) {
    printf("Decryption routine too large.\n");
    return 1;
  }
  printf("Size of stub = %d\n", decryptSize);

  // Now start putting data into memory as it will be laid out in
  // the packed executable.

  // Track the # of pieces of initialization data added.
  int numInitData = 0;

  // Store the RVA of the packed code furthest away from the stub.
  *(storageSpot + numInitData++) = (DWORD)baseCodeRVA;
    
  // Store original code entry RVA at storagespot next closest to
  // the stub.
  *(storageSpot + numInitData++) = (DWORD)optionHeader->AddressOfEntryPoint;

  // Store the image base (used with the code base RVA to figure out
  // where the code to unpack is in memory in the unpacker stub) at
  // the next closest spot.
  *(storageSpot + numInitData++) = (DWORD)optionHeader->ImageBase;

  // Store size of code (in bytes) to unpack at the spot closest to
  // the stub.
  *(storageSpot + numInitData++) = virtualCodeSize;

  // Add our decryption routine to storageSpot + (# of data DWORDS
  // added). The +(# of data DWORDS written) is there so that the
  // unpacker stub data added above is not overwritten by the stub.
  //
  // Note that storageSpot is a pointer to a DWORD, so adding 1 to
  // storageSpot advances by 1 DWORD, not 1 BYTE.
  memcpy(storageSpot + numInitData, decryptRoutine, decryptSize);
    
  // Now update the header for the last section (i.e. one with
  // highest RVA) and extend this by size needed and set it to
  // executable.

  // Add the size of the unpacker stub and its initialization data
  // to all of the size tracking fields in the IMAGE_OPTIONAL_HEADER.
  optionHeader->SizeOfImage += 0x2000;
  optionHeader->SizeOfCode += 0x2000;
  optionHeader->SizeOfInitializedData += 0x2000;

  // Set the new initial entry point to the unpacker stub.
  optionHeader->AddressOfEntryPoint = 
    // Start in last section...
    (DWORD)lastSection->VirtualAddress + 
    // At the end of its original data...
    (DWORD)lastSection->SizeOfRawData + 
    // Past the unpacker stub initialization data (4 DWORDs).
    (sizeof(DWORD))*numInitData;

  // Add the size of the unpacker stub and its initialization data
  // to all of the size tracking fields the last section header.
  lastSection->Misc.VirtualSize += 0x2000;
  lastSection->SizeOfRawData += 0x2000;
  lastSection->Characteristics = IMAGE_SCN_MEM_WRITE|
    IMAGE_SCN_MEM_READ|
    IMAGE_SCN_MEM_EXECUTE|
    IMAGE_SCN_CNT_UNINITIALIZED_DATA |
    IMAGE_SCN_CNT_INITIALIZED_DATA|
    IMAGE_SCN_CNT_CODE;//0xE00000E0;

  // Finally we need to set the main code section as writable for
  // our stub to decrypt it. We will do this by making ALL sections
  // writable.
  MakeAllSectionsWritable(firstSectionHeader, 
			  pNTHeader->FileHeader.NumberOfSections); 

  // Close the packed file.
  CloseHandle(hFile);
}
// Do a filetype on a function (? :-)
void function_filetype(FunctionHandle *handle)
{
	Cfg_Filetype *type,*last_type=0;
	Cfg_Function *func,*type_function=0,*old_function;
	struct List filechange_list;
	struct Node *node,*next=0;
	unsigned short qual;

	// Extract qualifier
	qual=(handle->data>>16)&0xffff;
	handle->data&=0xffff;

	// Backup function pointer
	old_function=handle->function;

	// Lock filetype list
	lock_listlock(&GUI->filetypes,FALSE);

	// Steal the filechange list
	NewList(&filechange_list);
	for (node=handle->filechange.lh_Head;node->ln_Succ;node=next)
	{
		next=node->ln_Succ;
		Remove(node);
		AddTail(&filechange_list,node);
	}

	// Got arguments?
	if (handle->args)
	{
		struct ArgArrayEntry *arg;

		// Go through list
		for (arg=(struct ArgArrayEntry *)handle->args->aa_List.mlh_Head;
			arg->ae_Node.mln_Succ;
			arg=(struct ArgArrayEntry *)arg->ae_Node.mln_Succ)
		{
			// Match filetype for this file
			if (!(type=filetype_identify(arg->ae_String,handle->data,0,qual)))
			{
				// Couldn't match. Was this a drag & drop operation?
				if (handle->flags&FUNCF_DRAG_DROP)
				{
					// Use "default" filetype (copy)
					type=default_filetype;
				}
			}

			// Got filetype?
			if (type)
			{
				// Get appropriate function
				if ((func=FindFunctionType(&type->function_list,handle->data)))
				{
					ExternalEntry *entry;

					// Different to the last type?
					if (last_type && type!=last_type)
					{
						// Anything in the external list?
						if (!(IsListEmpty((struct List *)&handle->external_list)) &&
							type_function)
						{
							Cfg_Function *copy;

							// Initialise handle function
							function_handle_init(handle,1);

							// Copy the function
							if ((copy=CopyFunction(type_function,handle->memory,0)))
							{
								// Set function pointer
								handle->function=copy;

								// Unlock the filetype list
								unlock_listlock(&GUI->filetypes);

								// Run function
								function_run_function(handle);

								// Free the function
								FreeFunction(copy);

								// Lock filetype list again
								lock_listlock(&GUI->filetypes,FALSE);

								// Steal new filechanges
								for (node=handle->filechange.lh_Head;node->ln_Succ;node=next)
								{
									next=node->ln_Succ;
									Remove(node);
									AddTail(&filechange_list,node);
								}
							}

							// Clear external list
							NewList((struct List *)&handle->external_list);
						}
					}

					// Save type pointer
					last_type=type;

					// Save function pointer
					type_function=func;

					// Create a new external entry
					if ((entry=new_external_entry(handle,arg->ae_String)))
					{
						// Add to external entry list
						AddTail((struct List *)&handle->external_list,(struct Node *)entry);
					}
				}
			}
		}
	}

	// Anything left in the external list?
	if (!(IsListEmpty((struct List *)&handle->external_list)) &&
		type_function)
	{
		Cfg_Function *copy;

		// Initialise handle function
		function_handle_init(handle,1);

		// Copy the function
		if ((copy=CopyFunction(type_function,handle->memory,0)))
		{
			// Set function pointer
			handle->function=copy;

			// Unlock the filetype list
			unlock_listlock(&GUI->filetypes);

			// Run function
			function_run_function(handle);

			// Free the function
			FreeFunction(copy);

			// Lock filetype list again
			lock_listlock(&GUI->filetypes,FALSE);

			// Steal new filechanges
			for (node=handle->filechange.lh_Head;node->ln_Succ;node=next)
			{
				next=node->ln_Succ;
				Remove(node);
				AddTail(&filechange_list,node);
			}
		}
	}

	// Unlock the filetype list
	unlock_listlock(&GUI->filetypes);

	// Restore function pointer
	handle->function=old_function;

	// Copy filechange list back
	for (node=filechange_list.lh_Head;node->ln_Succ;node=next)
	{
		next=node->ln_Succ;
		Remove(node);
		AddTail(&handle->filechange,node);
	}
}