...reposting this from another thread, but since you asked how to make a plugin:
QUOTE
DllMain: part of every dll, look on MSDN when it's called.
GetPluginVersion: as the comment says, leave it alone. It makes sure whether the plugin version and the SCMD2 version are compatible.
InitPlugin: called when the plugin is initialized, usually at SCMD2 startup. That messagebox you see when the sample plugin runs on SCMD2 startup is called on from here. Here is also where you set which sections of the map you request SCMD2 to give your plugin. SCMD2 will pretty much only give you TRIG and MBRF, which are the sections you need for a trigger editor. This is due to SCMD2 not being designed to have plugins altering other sections (which could cause crashes). However, if you have a good enough reason, you could convince SI to add support for other sections to be given.
HWND MainWindow: Handle to the SCMD2 main window. Useful to be assigned to a global handle so that you can disable it when your plugin runs.
HINSTANCE MainInstance: Handle to the instance of SCMD2.
AllocRam AllocMem
DeAllocRam DeleteMem
ReAllocRam ResizeMem: Memory allocation stuff, I don't know when these could be used. I once asked SI about it and he said TrigEdit could use them.
DWORD* RequestedSections: Pointer to an array of 8 (or maybe 9) DWORDs that are names of sections that your plugin requests SCMD2 to give.
PluginGetMenuString: this function will be called several times, for each section that you requested. It asks you to provide the menu item string under the "plugins" menu.
DWORD Section: The current section for which the function is asking the menu item string of.
CHAR* MenuStr: The string to which you copy the menu item string.
WORD StrLen: The maximum length of the menu item string. Check against this value before doing strcpy to MenuStr.
RunPlugin: this is when the user clicks on a menu item of your plugin. So, here is where the "meat" of your plugin goes. The datachunks contain everything you need for a trigger editing plugin.
TEngineData* EngineData: A pointer to the engine data structure (see SCMDPlugin.h).
DWORD CurSection: The section for which the plugin is being run. Either triggers or mission briefings.
CChunkData* Triggers: Pointer to the trigger datachunk (see SCMDPlugin.h). A datachunk is just the size of a section (DWORD) and the section data (array of BYTE).
CChunkData* MissionBriefing: Pointer to the mission briefing (MBRF) datachunk.
CChunkData* SwitchRenaming: Pointer to the switch renaming (SWNM) datachunk.
CChunkData* UnitProperties: Pointer to the unit properties (UPRP) datachunk.
CChunkData* UnitPropUsage: Pointer to the unit properties usage (UPUS) datachunk.
Here are the various structure notes from SCMDPlugin.h:
SCLocation/LocationNode: SCLocation contains the various location data, LocationNode is a node containing SCLocation and whether the data is used or not.
CChunkData: Datachunk structure, see above.
TEngineData: Engine data structure:
MapLocations: Always 256 of these, regardless of whether the map is SC or BW. (MRGN)
WavStringIndexii: Always 512 of these (map .wav string numbers). (WAV )
ActionLog: Null, see below.
ActionLogLevel: SCMD2 Output log data... SI never got around to giving the format to this.
DataInterface: Null, "until virtual class is implemented." Interpret this however you want.
CurSelLocation: Having the currently selected location display on the minimap of SCMD2 (feature that's not implemented yet).
UnitCustomNames: Don't use; use UnitNames instead (see below). String numbers: "0" indicates none, everything else is off by one (1-based). 228 entries.
ForceNames: String Numbers: "0" indicates none, everything else is off by one (1-based). 4 entries.
UnitNames: "char*[228] with non identical unit names."
TPluginInfo: Have no idea where this is used. It doesn't seem to be used anywhere else in the plugin, but TrigEdit might use it (or might have used it) for some odd reason.
UnitProp: Unit properties data chunk member. (UPRP)
Please note that I heard SI was considering to remove the plugins interface due to nobody actually bothering to make plugins, so you might wanna talk to him.
Edit: ...as for protection, it does a lot of stuff to the .chk that causes it to be corrupt to StarEdit/SF/SCMD2, but still be able to be read by SC. From a thread at BlizzForums (made a few changes from new info from DK, actually LW, and Min):
QUOTE
SC reads the last instance of each section, and the last "good" instance of STR, TRIG, and MBRF. "Good" means non-null in the case of STR (i.e. the section length isn't "0") and have at least one owned trigger in the case of TRIG/MBRF. Technically, it reads every instance of each section, but the last ones are the ones where data is "left alone", since there are no more duplicate sections to overwrite it.
This distinction is important in "dimensioned" sections (i.e. sections that have been sized via DIM): if the first instance of, say, MTXM, in a map that's 128x128 (full normal section length for MTXM: 32768) contains only the first 16384 bytes as "garbage" (what Uberation does sometimes) and the rest are correct, then the second duplicate whose section length is 16384 bytes and contains the "right" data overwrites those first 16384 bytes in the static array SC already created (SC doesn't resize the dimensioned arrays like it does with section-length dependent ones: DD2, UNIT, etc).
SC first reads the .chk in the map selection screen, where it looks for DIM, STR, SPRP, MTXM, ERA, FORC, SIDE and maybe a few other sections. If it doesn't find those, or if VCOD, VER, or (I think) OWNR aren't correct, it says that the scenario is invalid, or if the VER is different, then it says it's obsolete or something. Later on, if your map has those sections correct, but has a missing or corrupt, say, THG2, then it will crap out on you (the time of which depends on which section is missing or corrupt). Obviously, different game types load different sections, so SC will load a map fine without TRIG or MBRF or sections like that if the game type is "melee". The ones that aren't used ever are UPUS, DD2, IOWN, ISOM, TILE, WAV, IVER (I think), IVE2 (I think), and the upgrade sections not relating to your version (i.e. if the map is set as BW, SC will ignore upgrade sections like UPGS, TECS, etc... if the map is "hybrid", SC will ignore those "old" upgrade sections too... and if the map is "SC", then it will ignore the BW upgrade sections like PUPx, TECx, etc.)
Edit: A section can be "corrupt" if it's supposed to be a fixed length (i.e. 12 for OWNR), but deviates from that length (I think that the length being "more" works, but "less" doesn't; I forgot since I tested this close to a year ago). I think if stuff like UNIT isn't divisible by the length of a single UNIT structure, it's also "corrupt"... I don't know for sure about this, you might want to test it.
So, "static" sections (upgrade sections, things like OWNR, SPRP, FORC, etc.; their size doesn't change dynamically) are read correctly if they're at least the size they're supposed to be (exactly the size?). "Dynamic" sections I think work if they are divisible by the length of their single respective structures, though probably they'll work if they're any size. I think dimensioned sections work in any way, as long as they're present.
Basically, you might want to test the above 2 paragraphs for validity since I forgot how exactly it works and the .chk specs I talked about are on a HD I can't access right now.
...and STR works as long as its section length isn't "0" (yes, if it's one, it will give you garbage data, but it's read in SC anyway). STR also doesn't have to have exactly 1024 strings.